package com.maserb.monitor.alipay;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import com.maserb.monitor.common.AjaxResult;
import com.maserb.monitor.common.AjaxUtils;
import com.maserb.monitor.common.Func_T;
import com.maserb.monitor.entity.UserEntity;
import com.maserb.monitor.entity.card.RechargeRecordEntity;
import com.maserb.monitor.entity.schoolStudent.SchoolStudentEntity;
import com.maserb.monitor.repository.schoolStudent.RechargeRecordRepository;
import com.maserb.monitor.service.author_manage.UserService;
import com.maserb.monitor.service.remote.EcCardService;
import com.maserb.monitor.service.schoolStudent.SchoolStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝接口请求
 */
@Controller
@RequestMapping("/aliPay")
public class AliPayController {

    @Autowired
    private AliPayConfig alipayConfig;
    @Autowired
    private SchoolStudentService schoolStudentService;
    @Autowired
    private RechargeRecordRepository rechargeRecordRepository;
    @Autowired
    private EcCardService ecCardService;
    @Autowired
    private UserService userService;

    /**
     * 充值
     * @param studentId  学生id
     * @param type  人员类型 1：学生 2：老师
     * @param totalAmount  充值金额
     * @return
     */
    @RequestMapping("/pay")
    @ResponseBody
    public AjaxResult<String> pay(String studentId, String type, Double totalAmount) {
        RechargeRecordEntity recharge = new RechargeRecordEntity();

        if(StringUtils.isEmpty(type) || type.equals("1")) {
            SchoolStudentEntity student = schoolStudentService.findOne(studentId);
            recharge.setStudent(student);
            recharge.setCardNumber(student.getCardNumber());
        } else {
            UserEntity teacher = userService.findOne(studentId);
            recharge.setTeacher(teacher);
            recharge.setCardNumber(teacher.getCardNumber());
        }

        recharge.setCreateTime(new Date());
        recharge.setTotalAmount(totalAmount);
        recharge.setPayStatus("0"); //未支付
        recharge.setRemarks("支付宝充值");
        rechargeRecordRepository.save(recharge);

        AjaxResult<String> result = AjaxUtils.process(new Func_T<String>() {
            @Override
            public String invoke() throws Exception {
                AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getServerUrl(),
                        alipayConfig.getAppId(), alipayConfig.getPrivateKey(), AlipayConstants.FORMAT_JSON,
                        AlipayConstants.CHARSET_UTF8, alipayConfig.getAlipayPublicKey(), AlipayConstants.SIGN_TYPE_RSA2);
                //2  实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
                AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
                //3  SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。

                AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();

                model.setSubject("一卡通充值");
                model.setOutTradeNo(recharge.getId());
                model.setTimeoutExpress("30m");
                model.setTotalAmount(totalAmount.toString());
                model.setProductCode("QUICK_MSECURITY_PAY");
                request.setBizModel(model);
                request.setNotifyUrl(alipayConfig.getNotifyUrl());
                try {
                    //这里和普通的接口调用不同，使用的是sdkExecute
                    AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
                    return response.getBody() + "&tradeNo=" + recharge.getId();
                } catch (AlipayApiException e) {
                    e.printStackTrace();
                }
                return "ERROR";
            }
        });

        JSONObject extra = new JSONObject();
        extra.put("tradeNo", recharge.getId());
        result.setExtra(extra);
        return result;
    }

    @RequestMapping("/notify")
    public void notify(HttpServletRequest request) {
        //处理参数
        Map<String, String> params = new HashMap<String, String>(Maps.transformValues(request.getParameterMap(),
                input -> Joiner.on(",").join(input)));
        // 获取到返回的所有参数 先判断是否交易成功trade_status 再做签名校验
        // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
        // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
        // 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
        // 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
        String outTradeNo = params.get("out_trade_no");
        RechargeRecordEntity recharge =  rechargeRecordRepository.findById(outTradeNo).get();
        if(recharge != null) {
            recharge.setPayStatus("1"); //已支付
            rechargeRecordRepository.save(recharge);

            ecCardService.doAddRechargeRecord(recharge);
        }
    }
}
